哈囉!昨天使用 SWR 實作了一個小功能,讓使用者可以列出某 Github user 的所有公開 repository~ 今天用 Notion SDK 新增了一個新的頁面,顯示我的 Notion page 裡面的內容,可以在這裡看看喔。
想要可以用 Notion SDK 或呼叫 Notion API 之前,我們要去做這些步驟取得權限:
https://jadejs.notion.site/iTHome-0f3a86530c5e44d18004c5c689044c5d
,-
後面的一串字串是我們想要的 ID.env
檔裡面
NOTION_TOKEN=secret_**********************************
NOTION_PAGE_ID=0f3a86530c5e44d18004c5c689044c5d
page ID 其實是公開的資訊,所以不一定要放在 .env
裡~我們現在要安裝 Notion SDK,如果你們想要用 Notion API 也可以喔!不過我在這專案裡使用的是 SDK:
npm install @notionhq/client
# or
yarn add @notionhq/client
裝完之後我們可以開始用 SDK 了~
import { Client } from "@notionhq/client";
// 初始化 Client
const notion = new Client({
auth: process.env.NOTION_TOKEN, // 剛剛把 secret token 寫在 .env 裡面的那個!
});
豪!可以開始拿資料了~ Notion API 有提供很多 endpoints,例如我們今天要用的 pages.retrieve
,就是取得該 page 的內容。
export const getPage = async () => {
const pageId = process.env.NOTION_PAGE_ID; // 我們的 page ID
const response = await notion.pages.retrieve({ page_id: pageId });
// response 會是 page object
return response;
};
response
為 JSON 格式的 page object:
{
"object": "page",
"id": "b55c9c91-384d-452b-81db-d1ef79372b75",
"created_time": "2020-03-17T19:10:04.968Z",
"last_edited_time": "2020-03-17T21:49:37.913Z",
"parent": {
"type": "database_id",
"database_id": "48f8fee9-cd79-4180-bc2f-ec0398253067"
},
"archived": false,
"url": "https://www.notion.so/Avocado-b55c9c91384d452b81dbd1ef79372b75",
"icon": { "type": "emoji", "emoji": "?" },
"cover": {
"type": "external",
"external": {
"url": "https://website.domain/images/image.png"
}
},
"properties": {...}
}
使用 pages.retrieve
並不會拿到該 page 的 blocks
(page 的內容),只會拿到 page 的一些資訊和 properties
。
所以我們拿不到上面圖中的連結和文字,可是我們會拿到 title
,Actor
,還有封面圖,新增編輯時間等。
export const getBlocks = async () => {
// page 也是一種 block
const blockId = process.env.NOTION_PAGE_ID;
// 我們想拿到 page 裡的 blocks,這裡 block_id 等於 page ID
const response = await notion.blocks.children.list({ block_id: blockId });
// response 為 list of blocks
return response;
};
以上面的圖為例子,我們會拿到三個 blocks,第一個是連結,第二個是 Synopsis,第三個是 paragraph。
如果以上面的圖為例子,就是我今天做的頁面,我們大概會拿到像這樣的 response
:
{
"object": "list",
"results": [
{
"object": "block",
"id": "c164f4b2-ad9e-45df-859c-bbb5759eff00",
"created_time": "2021-09-26T08:42:00.000Z",
"last_edited_time": "2021-09-26T08:42:00.000Z",
"has_children": false,
"archived": false,
"type": "heading_1",
"heading_1": {
"text": [
{
"type": "text",
"text": { "content": "2021 鐵人賽 | iT邦幫忙", "link": null },
"annotations": {
"bold": false,
"italic": false,
"strikethrough": false,
"underline": false,
"code": false,
"color": "default"
},
"plain_text": "2021 鐵人賽 | iT邦幫忙",
"href": null
}
]
}
},
{
"object": "block",
"id": "0f707dff-1498-4416-a156-7c6ef2a026d1",
"created_time": "2021-09-26T08:42:00.000Z",
"last_edited_time": "2021-09-26T08:42:00.000Z",
"has_children": false,
"archived": false,
"type": "heading_3",
"heading_3": {
"text": [
{
"type": "text",
"text": {
"content": "製作你的無程式碼(No-code)個人網頁 ft. Next.js, SWR, 串 Youtube, IG, Github, Notion API ~",
"link": null
},
"annotations": {
"bold": false,
"italic": false,
"strikethrough": false,
"underline": false,
"code": false,
"color": "default"
},
"plain_text": "製作你的無程式碼(No-code)個人網頁 ft. Next.js, SWR, 串 Youtube, IG, Github, Notion API ~",
"href": null
}
]
}
},
...
],
}
每個 block 會有 id
,type
,新增編輯時間等,也包含該 block 的內容,像 heading_3
的 block,裡面包含了 text
的陣列,每一個 text object 會有自己的格式 (formatting),寫在 annotations
裡面。我們可以根據 annotations
還有 href
的資訊決定該怎麼顯示這個 text object (物件)~
今天使用了 getStaticProps
抓取資料,可是也可以用 getServerSideProps
,而且用 SSR 的話,頁面可以拿到最新的內容!不過我這頁面內容應該不會變,所以決定這麼寫:
// pages/notion.js
export async function getStaticProps() {
// 可以直接把 getPage 和 getBlocks import 進來~
const page = await getPage();
const blocks = await getBlocks();
const data = { ...page, blocks };
return {
props: { data },
};
}
今天看了 Notion API 的文件,發現抓完資料還要做多處理!不過這也讓我們有更多的彈性,想怎麼顯示我們拿到的資料都可以~ 所以我從一開始打算把 Notion 當成 CMS 或是資料庫,把資料都寫在 Notion 裡,然後再用 API 取這些資料去顯示。今天的小功能有讓我覺得好像離目標更近一步了!XD
大家可以看看在這裡,然後 Notion 的 page 在這裡~
祝大家週末愉快!
晚安 <3